#pragma once
#include"global_var.cpp"

class pri
{
public:
    static inline void DFF_PRI(std::vector<char*>& para) noexcept;
    static inline void XNOR(std::vector<char*>& para) noexcept;
    static inline void XOR(std::vector<char*>& para) noexcept;
    static inline void AND(std::vector<char*>& para) noexcept;
    static inline void NAND(std::vector<char*>& para) noexcept;
    static inline void OR(std::vector<char*>& para) noexcept;
    static inline void NOR(std::vector<char*>& para) noexcept;
    static inline void BUF(std::vector<char*>& para) noexcept;
    static inline void NOT(std::vector<char*>& para) noexcept;
    static inline void MUX_2(std::vector<char*>& para) noexcept;
};

inline void pri::DFF_PRI(std::vector<char*>& para) noexcept
{   //para={0 : next_Q , 1 : set , 2 : reset , 3 : new_clock , 4 : D , 5 : old_clock , 6 : old_Q , 7 : old_set , 8 : old_reset}
    if(*(para[1])=='1'|| *(para[7])=='1')  *(para[0])='1';              //set|old_set   = 1
    else if(*(para[2]) == '1'|| *(para[8]) == '1') *(para[0])='0';      //reset|old_reset = 1
    else if(*(para[3]) == '1'&& *(para[5]) == '0')                      //clock 0->1
        *(para[0] )= *(para[4]);
    else if(*(para[3]) == '0'|| *(para[5]) == '1')                      //hold
        *(para[0]) = *(para[6]);
    else *(para[0]) = 'x';
}

inline void pri::XNOR(std::vector<char*>& para) noexcept
{
    XOR(para);
    if(*(para[0]) != 'x')
        *(para[0]) = (( *(para[0]) == '1')?'0':'1');
}

inline void pri::XOR(std::vector<char*>& para) noexcept
{
    *(para[0]) = *(para[1]);
    if(*(para[0]) == 'x') return ;
    for(char i=2,sz = para.size();i<sz;++i)
        if(*(para[i]) == 'x') 
        {
            *(para[0]) = 'x';
            return ;
        }
        else if(*(para[i]) == *(para[0]))
            *(para[0]) ='0';
        else
            *(para[0]) ='1';
}

inline void pri::AND(std::vector<char*>& para) noexcept
{
    *(para[0]) = '1';
    for(char i=1,sz = para.size();i<sz;++i)
        if(*(para[i]) == '0')
        {
            *(para[0]) = '0';
            return ;
        }
        else if(*(para[i]) == 'x')
            *(para[0]) ='x';
}

inline void pri::NAND(std::vector<char*>& para) noexcept
{
    *(para[0]) = '0';
    for(char i=1,sz = para.size();i<sz;++i)
        if(*(para[i]) == '0')
        {
            *(para[0]) ='1';
            return ;
        }
        else if(*(para[i]) =='x')
            *(para[0]) ='x';
}

inline void pri::OR(std::vector<char*>& para) noexcept
{
    *(para[0]) = '0';
    for(char i=1,sz = para.size();i<sz;++i)
        if(*(para[i]) == '1')
        {
            *(para[0])='1';
            return ;
        }
        else if(*(para[i]) == 'x')
            *(para[0]) = 'x';
}

inline void pri::NOR(std::vector<char*>& para) noexcept
{
    *(para[0]) = '1';
    for(char i=1,sz=para.size();i<sz;++i)
        if(*(para[i]) == '1')
        {
            *(para[0]) = '0';
            return ;
        }
        else if(*(para[i]) == 'x')
            *(para[0]) = 'x';
}

inline void pri::BUF(std::vector<char*>& para) noexcept
{
    *(para[0]) =  *(para[1]);
}

inline void pri::NOT(std::vector<char*>& para) noexcept
{
    if(*(para[1]) == 'x')
        *(para[0]) = 'x';
    else 
        *(para[0]) = ((*(para[1]) == '1')?'0':'1');
}

inline void pri::MUX_2(std::vector<char*>& para) noexcept
{       //para = {out,sel,A0,A1}
        //mux 0 A0  / 1 A1
    if(*(para[1])!='x')
        *(para[0]) = ((*(para[1])=='0')?*(para[2]):*(para[3]));
    else
    {
        if(*(para[2])=='1'&&*(para[3])=='1')
            *(para[0]) = '1';
        else if(*(para[2])=='0'&&*(para[3])=='0')
            *(para[0]) = '0';
        else 
            *(para[0]) = 'x';
    }
}


